/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.gui.widgets.layouts;

import edu.umd.cs.piccolo.PNode;

@SuppressWarnings("serial")
public class GridLayout extends Layout {
    
    public GridLayout(PNode parent, double rowColumRatio, double margin, double spacing) {
        super(parent,margin,spacing);
        m_rowColumRatio = rowColumRatio;
    }

    public void layoutChildren() {
        double xOffset = m_margin;
        double yOffset = m_margin;
        
        // For a grid layout, the children are laid out in a grid, according
        // to the "aspect ratio". The aspect ratio is not a true ratio
        // of the resulting width and height of the layout, but the ratio
        // of rows to columns in the grid
        
        // The first step is to calculate the number of rows and columns that 
        // match the ratio the closest. We're not being pedantic here, merely 
        // approximating. 
        
        // rows/colums = ratio
        // rows * colums = numItems
        //
        // r.c * r/c = r^2 = ratio*numItems
        
        
        double numItems = getChildrenCount();
        if ( numItems > 0 ) {
            double r = Math.sqrt(m_rowColumRatio*(numItems));
            double c = r / m_rowColumRatio;

            // Since the actual rows and colums are integers and 
            // the exat aspect ratio will not be achieved, create 
            // approximate integer numbers of rows and oclums
            int numRows = (int)r;
            int numColumns = (int)numItems/numRows + 1;
//          int numRows = (int)Math.round(r);
//          int numColumns = (int)Math.round(c);
            if ( numRows * numColumns < numItems ) {
                System.out.println(
                        "ration,r,c,rows,columns,numitems: " + m_rowColumRatio + ","
                        + r + "," + c + "," 
                        + numRows + "," + numColumns + "," + numItems);
            }
            assert ( numRows * numColumns >= numItems);

            // First we have to calculate the maximum width and height of the items
            // per row and per column.
            double[] maxWidths = new double[numColumns];
            double[] maxHeights = new double[numRows];

            for ( int index = 0; index < getChildrenCount(); ++index ) {
                int colIndex = index % numColumns;
                int rowIndex = index / numColumns; 

                PNode child = getChild(index);
                maxWidths[colIndex] = Math.max(child.getFullBounds().getWidth(), maxWidths[colIndex]);
                maxHeights[rowIndex] = Math.max(child.getFullBounds().getHeight(), maxHeights[rowIndex]);
            }

            // Do the layout
            double lastXOffset = m_margin;
            double lastYOffset = m_margin;
            for ( int index = 0; index < getChildrenCount(); ++index ) {
                int colIndex = index % numColumns;
                int rowIndex = index / numColumns; 

                if ( colIndex == 0 ) {
                    xOffset = m_margin;
                    if ( rowIndex == 0 ) {
                        yOffset = m_margin;
                    }
                    else
                    {
                        yOffset = lastYOffset + maxHeights[rowIndex-1] + m_spacing; 
                    }
                } else {
                    xOffset = lastXOffset + maxWidths[colIndex - 1] + m_spacing;
                }

                PNode child = getChild(index);
                child.setOffset(xOffset,yOffset);

                lastXOffset = xOffset;
                lastYOffset = yOffset;
            }
        }
    }
    

    double m_rowColumRatio;
}
